{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The CIFAR-10 Dataset\n",
    "* Contains 10 categories of images\n",
    " * airplane\n",
    " * automobile\n",
    " * bird\n",
    " * cat\n",
    " * deer\n",
    " * dog\n",
    " * frog\n",
    " * horse\n",
    " * ship\n",
    " * truck"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Let's Begin training out model for CIFAR-10 using a deeper CNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x_train shape: (50000, 32, 32, 3)\n",
      "50000 train samples\n",
      "10000 test samples\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d_1 (Conv2D)            (None, 32, 32, 32)        896       \n",
      "_________________________________________________________________\n",
      "activation_1 (Activation)    (None, 32, 32, 32)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_2 (Conv2D)            (None, 30, 30, 32)        9248      \n",
      "_________________________________________________________________\n",
      "activation_2 (Activation)    (None, 30, 30, 32)        0         \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 15, 15, 32)        0         \n",
      "_________________________________________________________________\n",
      "dropout_1 (Dropout)          (None, 15, 15, 32)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_3 (Conv2D)            (None, 15, 15, 64)        18496     \n",
      "_________________________________________________________________\n",
      "activation_3 (Activation)    (None, 15, 15, 64)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_4 (Conv2D)            (None, 13, 13, 64)        36928     \n",
      "_________________________________________________________________\n",
      "activation_4 (Activation)    (None, 13, 13, 64)        0         \n",
      "_________________________________________________________________\n",
      "max_pooling2d_2 (MaxPooling2 (None, 6, 6, 64)          0         \n",
      "_________________________________________________________________\n",
      "dropout_2 (Dropout)          (None, 6, 6, 64)          0         \n",
      "_________________________________________________________________\n",
      "flatten_1 (Flatten)          (None, 2304)              0         \n",
      "_________________________________________________________________\n",
      "dense_1 (Dense)              (None, 512)               1180160   \n",
      "_________________________________________________________________\n",
      "activation_5 (Activation)    (None, 512)               0         \n",
      "_________________________________________________________________\n",
      "dropout_3 (Dropout)          (None, 512)               0         \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 10)                5130      \n",
      "_________________________________________________________________\n",
      "activation_6 (Activation)    (None, 10)                0         \n",
      "=================================================================\n",
      "Total params: 1,250,858\n",
      "Trainable params: 1,250,858\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "from __future__ import print_function\n",
    "import keras\n",
    "from keras.datasets import cifar10\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Dropout, Activation, Flatten\n",
    "from keras.layers import Conv2D, MaxPooling2D\n",
    "from keras.models import load_model\n",
    "import os\n",
    "\n",
    "batch_size = 32\n",
    "num_classes = 10\n",
    "epochs = 1\n",
    "\n",
    "# Loads the CIFAR dataset\n",
    "(x_train, y_train), (x_test, y_test) = cifar10.load_data()\n",
    "\n",
    "# Display our data shape/dimensions\n",
    "print('x_train shape:', x_train.shape)\n",
    "print(x_train.shape[0], 'train samples')\n",
    "print(x_test.shape[0], 'test samples')\n",
    "\n",
    "# Format our training data by Normalizing and changing data type\n",
    "x_train = x_train.astype('float32')\n",
    "x_test = x_test.astype('float32')\n",
    "x_train /= 255\n",
    "x_test /= 255\n",
    "\n",
    "# Now we one hot encode outputs\n",
    "y_train = keras.utils.to_categorical(y_train, num_classes)\n",
    "y_test = keras.utils.to_categorical(y_test, num_classes)\n",
    "\n",
    "model = Sequential()\n",
    "# Padding = 'same'  results in padding the input such that\n",
    "# the output has the same length as the original input\n",
    "model.add(Conv2D(32, (3, 3), padding='same',\n",
    "                 input_shape=x_train.shape[1:]))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Conv2D(32, (3, 3)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(MaxPooling2D(pool_size=(2, 2)))\n",
    "model.add(Dropout(0.25))\n",
    "\n",
    "model.add(Conv2D(64, (3, 3), padding='same'))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Conv2D(64, (3, 3)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(MaxPooling2D(pool_size=(2, 2)))\n",
    "model.add(Dropout(0.25))\n",
    "\n",
    "model.add(Flatten())\n",
    "model.add(Dense(512))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Dropout(0.5))\n",
    "model.add(Dense(num_classes))\n",
    "model.add(Activation('softmax'))\n",
    "\n",
    "# initiate RMSprop optimizer and configure some parameters\n",
    "opt = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)\n",
    "\n",
    "# Let's create our model\n",
    "model.compile(loss = 'categorical_crossentropy',\n",
    "              optimizer = opt,\n",
    "              metrics = ['accuracy'])\n",
    "\n",
    "print(model.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Training Our Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 50000 samples, validate on 10000 samples\n",
      "Epoch 1/1\n",
      "26528/50000 [==============>...............] - ETA: 1:52 - loss: 1.9440 - acc: 0.2806"
     ]
    }
   ],
   "source": [
    "history = model.fit(x_train, y_train,\n",
    "          batch_size=batch_size,\n",
    "          epochs=epochs,\n",
    "          validation_data=(x_test, y_test),\n",
    "          shuffle=True)\n",
    "\n",
    "model.save(\"/home/deeplearningcv/DeeplearningCV/Trained Models/cifar_simple_cnn_2.h5\")\n",
    "\n",
    "# Evaluate the performance of our trained model\n",
    "scores = model.evaluate(x_test, y_test, verbose=1)\n",
    "print('Test loss:', scores[0])\n",
    "print('Test accuracy:', scores[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Plotting our Accuracy and Loss Charts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plotting our loss charts\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "history_dict = history.history\n",
    "\n",
    "loss_values = history_dict['loss']\n",
    "val_loss_values = history_dict['val_loss']\n",
    "epochs = range(1, len(loss_values) + 1)\n",
    "\n",
    "line1 = plt.plot(epochs, val_loss_values, label='Validation/Test Loss')\n",
    "line2 = plt.plot(epochs, loss_values, label='Training Loss')\n",
    "plt.setp(line1, linewidth=2.0, marker = '+', markersize=10.0)\n",
    "plt.setp(line2, linewidth=2.0, marker = '4', markersize=10.0)\n",
    "plt.xlabel('Epochs') \n",
    "plt.ylabel('Loss')\n",
    "plt.grid(True)\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plotting our accuracy charts\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "history_dict = history.history\n",
    "\n",
    "acc_values = history_dict['acc']\n",
    "val_acc_values = history_dict['val_acc']\n",
    "epochs = range(1, len(loss_values) + 1)\n",
    "\n",
    "line1 = plt.plot(epochs, val_acc_values, label='Validation/Test Accuracy')\n",
    "line2 = plt.plot(epochs, acc_values, label='Training Accuracy')\n",
    "plt.setp(line1, linewidth=2.0, marker = '+', markersize=10.0)\n",
    "plt.setp(line2, linewidth=2.0, marker = '4', markersize=10.0)\n",
    "plt.xlabel('Epochs') \n",
    "plt.ylabel('Accuracy')\n",
    "plt.grid(True)\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Let's run some tests"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "from keras.models import load_model\n",
    "\n",
    "img_row, img_height, img_depth = 32,32,3\n",
    "classifier = load_model('/home/deeplearningcv/DeepLearningCV/Trained Models/cifar_simple_cnn.h5')\n",
    "color = True \n",
    "scale = 8\n",
    "\n",
    "def draw_test(name, res, input_im, scale, img_row, img_height):\n",
    "    BLACK = [0,0,0]\n",
    "    res = int(res)\n",
    "    if res == 0:\n",
    "        pred = \"airplane\"\n",
    "    if res == 1:\n",
    "        pred = \"automobile\"\n",
    "    if res == 2:\n",
    "        pred = \"bird\"\n",
    "    if res == 3:\n",
    "        pred = \"cat\"\n",
    "    if res == 4:\n",
    "        pred = \"deer\"\n",
    "    if res == 5:\n",
    "        pred = \"dog\"\n",
    "    if res == 6:\n",
    "        pred = \"frog\"\n",
    "    if res == 7:\n",
    "        pred = \"horse\"\n",
    "    if res == 8:\n",
    "        pred = \"ship\"\n",
    "    if res == 9:\n",
    "        pred = \"truck\"\n",
    "        \n",
    "    expanded_image = cv2.copyMakeBorder(input_im, 0, 0, 0, imageL.shape[0]*2 ,cv2.BORDER_CONSTANT,value=BLACK)\n",
    "    if color == False:\n",
    "        expanded_image = cv2.cvtColor(expanded_image, cv2.COLOR_GRAY2BGR)\n",
    "    cv2.putText(expanded_image, str(pred), (300, 80) , cv2.FONT_HERSHEY_COMPLEX_SMALL,3, (0,255,0), 2)\n",
    "    cv2.imshow(name, expanded_image)\n",
    "\n",
    "\n",
    "for i in range(0,10):\n",
    "    rand = np.random.randint(0,len(x_test))\n",
    "    input_im = x_test[rand]\n",
    "    imageL = cv2.resize(input_im, None, fx=scale, fy=scale, interpolation = cv2.INTER_CUBIC) \n",
    "    input_im = input_im.reshape(1,img_row, img_height, img_depth) \n",
    "    \n",
    "    ## Get Prediction\n",
    "    res = str(classifier.predict_classes(input_im, 1, verbose = 0)[0])\n",
    "              \n",
    "    draw_test(\"Prediction\", res, imageL, scale, img_row, img_height) \n",
    "    cv2.waitKey(0)\n",
    "\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
